﻿#region Description
/*  File Name:      MEComponentManager.cs
 *  Author:         Adam Goodchild
 *  
 *  Description:    This class is used to Manage all MinimizeEngine components.
 *                  Contains:-
 *                   - Master List of all Components
 *                   - List of all Renderable Components
 *                   - List of all Load Components
 *                   - List of all Collision Components
*/
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MinimizeEngine.Interfaces;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace MinimizeEngine.Managers
{
    public sealed class MEComponentManager : DrawableGameComponent
    {
        #region Fields
        private static readonly Dictionary<String, MESceneObjectInterface> mMasterComponentList = new Dictionary<string, MESceneObjectInterface>();
        private static readonly Dictionary<String, MERenderableInterface> mMasterRenderableList = new Dictionary<string, MERenderableInterface>();
        private static readonly Dictionary<String, MELoadInterface> mMasterLoadList = new Dictionary<string, MELoadInterface>();
        private static readonly Dictionary<String, MEUpdateInterface> mMasterUpdateList = new Dictionary<string, MEUpdateInterface>();
        private static readonly Dictionary<String, MEInitializableInterface> mMasterInitializableList = new Dictionary<string, MEInitializableInterface>();
        private static readonly Dictionary<String, IDisposable> mMasterDisposableList = new Dictionary<string, IDisposable>();
        private static readonly Dictionary<String, MECollisionInterface> mMasterCollisionList = new Dictionary<string, MECollisionInterface>();
        #endregion

        #region Properties

        public static void AddNewComponent(String name, MESceneObjectInterface component)
        {
            mMasterComponentList.Add(name, component);

            if(component is MEInitializableInterface)
            {
                mMasterInitializableList.Add(name, (MEInitializableInterface)component);
            }

            if(component is MELoadInterface)
            {
                mMasterLoadList.Add(name, (MELoadInterface)component);
            }

            if (component is MERenderableInterface)
            {
                mMasterRenderableList.Add(name, (MERenderableInterface)component);
            }

            if(component is MEUpdateInterface)
            {
                mMasterUpdateList.Add(name, (MEUpdateInterface)component);
            }

            if(component is IDisposable)
            {
                mMasterDisposableList.Add(name, (IDisposable)component);
            }
        }

        internal static T GetComponent<T>(String name)
        {
            if(mMasterComponentList.ContainsKey(name) && mMasterComponentList[name] is T)
            {
                return (T)mMasterComponentList[name];
            }

            throw new MEComponentException("Sorry, no Component with the name " + name + " was found...");
        }

        #endregion

        #region Initialization

        internal MEComponentManager(Game game) : base(game)
        {

        }

        public override void Initialize()
        {
            foreach (MEInitializableInterface initComponent in mMasterInitializableList.Values)
            {
                initComponent.Initialize();
            }
            base.Initialize();
        }

        protected override void LoadContent()
        {
            foreach (MELoadInterface loadComponent in mMasterLoadList.Values)
            {
                loadComponent.LoadContent();
            }

            base.LoadContent();
        }

        protected override void UnloadContent()
        {
            foreach (MELoadInterface loadComponent in mMasterLoadList.Values)
            {
                loadComponent.UnloadContent();
            }

            base.UnloadContent();
        }

        protected override void Dispose(bool disposing)
        {
            foreach (IDisposable dispComponent in mMasterDisposableList.Values)
            {
                dispComponent.Dispose();
            }
            base.Dispose(disposing);
        }

        #endregion

        #region Update

        public override void Update(GameTime gameTime)
        {
            foreach (MEUpdateInterface updateComponent in mMasterUpdateList.Values)
            {
                updateComponent.Update();
            }
            base.Update(gameTime);
        }

        #endregion

        #region Exceptions

        internal sealed class MEComponentException : Exception
        {
            internal MEComponentException(String s) : base(s)
            {

            }
        }

        #endregion
    }
}
